package com.fzz.learnitservice.interceptor;

import cn.hutool.jwt.JWTException;
import com.fzz.learnitservice.context.UserContext;
import com.fzz.learnitservice.pojo.properties.JwtProperties;
import com.fzz.learnitservice.utils.JwtUtils;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerInterceptor;

/**
 * 请求拦截器
 * 从JWT中提取用户ID，并使用ThreadLocal存储，供Service层使用
 */
@Slf4j
@Component
@RequiredArgsConstructor
public class RequestInterceptor implements HandlerInterceptor {

    private final JwtUtils jwtUtils;
    private final JwtProperties jwtProperties;
    private static final String accessTokenKey = "login:token:";
    private final RedisTemplate<String, String> redisTemplate;

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {

        String requestURI = request.getRequestURI();

        if (requestURI.startsWith("/access/")) {
            return true;    // 登录请求直接放行
        }

        // 从请求头获取JWT Token
        String authHeader = request.getHeader(jwtProperties.getHeader());
        if (authHeader == null || !authHeader.startsWith("Bearer ")) {
            log.warn("请求缺少有效的Authorization头");
            response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
            return false;
        }

        // 提取Token
        String token = authHeader.substring(7); // 移除 "Bearer " 前缀

        // 验证Token
        if (!jwtUtils.validateToken(token)) {
            log.warn("请求的Token无效或已过期");
            response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
            return false;
        }

        try {
            // 从Token中提取用户ID
            Long userId = jwtUtils.getUserId(token);

            String redisKey = accessTokenKey + userId;
            String token2 = redisTemplate.opsForValue().get(redisKey);
            if(!token.equals(token2)) {
                throw new RuntimeException("该用户账号异常，请联系后台管理员");
            }
            
            // 将用户ID存储到ThreadLocal中，供后续使用
            UserContext.setUserId(userId);

            return true;
        } catch (JWTException e) {
            log.error("从Token中提取用户ID失败", e);
            response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
            return false;
        }


    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        // 请求完成后清除ThreadLocal，防止内存泄漏
        UserContext.clear();
    }
}
